/**
 * javascript Comment Templates(jCT)
 *
 * licensed under the MIT license.
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Author achun (achun at gmail.com)
 * Create Date: 2008-2-21
 * Last Date: 2008-3-25
 * Revision:1.00
 * 传入参数:参数为复用型,通过类型和值进行判断
 * todo:
 *   typeof(todo):
 *     string:
 *       !!:剔除
 *       parse:只解析不装配
 *     object:用于得到视图的数据
 * txt:模板
 *   typeof(txt):
 *     undefined:txt=document.body.innerHTML;
 *     string:txt视为模板
 * 返回值:{ok:bool,txt:string,fun:{id:function(dat),...}}
 * ok:执行是否成功
 * txt:返回视图代码
 * fun:存储模板函数列表
 *   dat:数据参数
 *   返回值:视图
 */
var jCT = window.jCT = function(todo,txt){
	var re={ok:false,txt:null,fun:false};
	var ve=0,typ=typeof (txt),savetpl=[];
	switch (typ) {
	case 'string':break;
	case 'undefined':txt = document.body.innerHTML;break;
	}
	todo=todo||'parse';
	if (todo[0]=='!') {//剔除
			while(cut('<!--!!','!-->'));
			if (todo[1]=='#') {
				ve=0;while(cut('<!--##','#-->'));
			}
			ve=0;while(cut('<!--!#','#-->'));
			re.txt=txt;
			re.ok = true;
	}else if(todo=='parse'){
		var __CTA__ = parse();
		var funstr = toFunStr();
		funstr=eval('""||'+funstr);
		re.fun=function(dat){
			var r=false;
			var jct=funstr;
			var __CTA__=__CTA__;
			try {
				r=jct(dat);
			}catch (ex) {
				alert(ex.description || ex.message);
			}
			return r;
		}
		re.fun.toString=function(){return jCT.ver;};
		re.ok = true;
		return re;
	}else if (typeof(todo)=='object'){
		var __CTA__ = parse();
		var funstr = toFunStr();
		try {
			funstr = eval('""||'+funstr);
			re.txt = funstr(todo);
			re.ok=true;
		}catch (ex) {
			alert(ex.description || ex.message);
			return re;
		}
	}else{
		return re;
	}
	//存储模板处理
	if (savetpl.length){
		re.fun={};
		for (var i=0; i<savetpl.length; i++) {
			var s=savetpl[i].indexOf('#')+1;
			var e=savetpl[i].indexOf('-->',s);
			var idlist=savetpl[i].slice(s,e).split(',');
			s=savetpl[i].indexOf('<!--#',e);
			txt = savetpl[i].slice(e+3,s);
			for (var j=0; j<idlist.length; j++) {
				var id=(idlist[j] || "").replace( /^\s+|\s+$/g, "" );
				if (id!=''){
					var tmp=jCT(false,txt);
					if (tmp.ok) {
						re.fun[id]=jCT.savefun[id]=tmp.fun;
					}
				}
			}
		}
	}
	switch (typ) {
	case 'string':break;
	case 'undefined':document.body.innerHTML = re.txt;break;
	}
	return re;

	function toFunStr (){
		var fun=[];
		fun.push("(function (__CTD__){");
		fun.push("var __CTV__ = []; "+
			"with(__CTD__){");
		for (var i=0; i<__CTA__.length; i++) {
			if (typeof (__CTA__[i])=='string') {
				if ( __CTA__[i]!='') fun.push('__CTV__.push(__CTA__['+i+']);');
			}else{
				__CTA__[i][1]=__CTA__[i][1] || '';
				switch (__CTA__[i][0]) {
				case '@':
				case '=':if ( __CTA__[i][1]!='')
						fun.push('__CTV__.push('+__CTA__[i][1]+');');break;
				case 'end':      fun.push('}');break;
				case 'var':      fun.push('var '+ __CTA__[i][1] + ';');break;
				case 'continue': fun.push('continue '+ __CTA__[i][1] + ';');break;
				case 'break':    fun.push('break '+ __CTA__[i][1] + ';');break;
				case 'elseif':   fun.push("}else if("+__CTA__[i][1]+"){");break;
				case 'else':     fun.push("}else{"+__CTA__[i][1]);break;
				case 'function': fun.push('function' + __CTA__[i][1] + ';');break;
				case 'with':     fun.push("with("+__CTA__[i][1]+"){");break;
				case 'if':       fun.push("if("+__CTA__[i][1]+"){");break;
				case 'while':    fun.push("while("+__CTA__[i][1]+"){");break;
				case 'do':    fun.push("do("+__CTA__[i][1]+"){");break;
				case 'enddo':    fun.push("}while("+__CTA__[i][1]+");");break;
				case 'for':      fun.push("for("+__CTA__[i][1]+"){");break;
				case 'switch':   fun.push("switch("+__CTA__[i][1]+"){");break;
				case 'case':     fun.push('case '+__CTA__[i][1] + ':');break;
				case 'default':  fun.push('default:');break;
				case 'run':      fun.push(__CTA__[i][1] + ';');break;
				}
			}
		}
		fun.push("}return __CTV__.join('');})");
		return fun.join('');
	}
	function cut(begin,end,del) {
		if (typeof (del)=='undefined')	del=true;
		var s=ve,b=txt.indexOf(begin,ve);
		if(b<0) return false;
		ve=txt.indexOf(end,b+begin.length);
		if(ve<0) return false;
		ve=ve+end.length;
		switch(del) {
		case 'cut':
			var str=txt.slice(b,ve);
			txt = txt.slice(0,b) + txt.slice(ve);
			return str;
			break;
		case true:
			txt = txt.slice(0,b) + txt.slice(ve);
			return true;
			break;
		case false:
			return txt.slice(b,ve);
			break;
		}
	}
	function parse (){
		function parseV(str){
			if (str=='') return [];
			var rea=[];
			ve=0;
			var a = exev(str);
			if (!a) return str;
			while(a){
				if (a[1][0]==' ')
					rea.push(a[0] +'{'+a[1].slice(1)+'}');
				else{
					if (a[0]!='') rea.push(a[0]);
					rea.push(['@',a[1]]);
				}
				a = exev(str);
			}
			rea.push(str.substring(ve));
			return rea;
		}
		function exev(str) {
			var s=ve,b=str.indexOf('+-',ve);
			if(b<0) return false;
			ve=str.indexOf('-+',b+2);
			if(ve<0){ve=s; return false;}
			ve=ve+2;
			return [str.slice(s,b),unescape(str.slice(b+2,ve-2))];
		}
		function exec() {
			var s=ce,b=txt.indexOf('<!--',ce);
			if(b<0) return false;
			ce=txt.indexOf('-->',b+4);
			if(ce<0){ce=s; return false;}
			ce=ce+3;
			return [txt.slice(s,b),txt.slice(b+4,ce-3)];
		}
		// 删除 view标记 / 注释
		var res=[],a,lasttxt,tag,ce=0;
		//ve=0;while(cut('<!--!!','!-->'));
		ve=0;while(cut('<!--##','#-->'));
		ve=0;while(cut('<!----','-->'));
		var tpl;
		ve=0;
		while(true){
			tpl=cut('<!--!#','#-->','cut');//分离存储
			if (!tpl) break;
			savetpl.push(tpl);
		}
		ve=0;
		while(true){
			tpl=cut('<!--#','#-->',false);//存储
			if (!tpl) break;
			savetpl.push(tpl);
		}
		//线性转换模板到数组
		var tagre=/(?:^(run|var|with|function|if|elseif|while|for|continue|break|switch|case|default)\b((?:.|\r|\n)+))/im;
		ve=0;
		a=exec();
		while(a){
			//值表达式 处理
			if (a[0]!='')
				res = res.concat(parseV(a[0]));
			//结构语句 处理
			if (a[1]=='end' || a[1]=='else' || a[1]=='do')
				a[1] =[a[1]];
			else
				a[1] = (tagre.exec(a[1]) || '').slice(1);
			if (a[1]!='') res.push(a[1]);
			a=exec();
		}
		txt=txt.substring(ce);
		if (txt!='') res = res.concat(parseV(txt));
		return res;
	}
};
jCT.ver='javascript Comment Templates 1.00 Last Date: 2008-3-25';
jCT.toString=function(){return {};};
jCT.savefun={};
jCT.savefun.toString=function(){return jCT.ver;};